package org.ala.distributed_database_transaction.commons;

import org.ala.distributed_transaction_commons.AbstractDistributedTransaction;
import org.ala.distributed_transaction_commons.DistributedTransactionStatus;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;


/**
 * 数据库分布式事务公共行为
 * 
 * @author 骆毅(ala)
 * @date 2024年2月20日
 */
public abstract class AbstractDataBaseTransaction extends AbstractDistributedTransaction {

	
	/**
	 * 本地事务状态对象
	 */
	protected TransactionStatus tx = null;
	/**
	 * 事务管理器引用
	 */
	protected DataSourceTransactionManager dataSourceTransactionManager;
	
	
	public AbstractDataBaseTransaction(DataSourceTransactionManager dataSourceTransactionManager) {
		super();
		this.dataSourceTransactionManager = dataSourceTransactionManager;
	}


	/**
	 * 取数据库事务状态对象
	 */
	protected TransactionStatus getDBTransaction() {
		if (dataSourceTransactionManager == null) {
			throw new RuntimeException("[" + this.getClass().getSimpleName() + " getDBTransaction] 当前环境中可能存在多个DataSourceTransactionManager，请使用begin(DataSourceTransactionManager)方法指定事务管理器方式开启分布式事务");
		}
		
		if (tx == null) {
			synchronized (this) {
				if (tx == null) {
					tx = dataSourceTransactionManager.getTransaction(transactionDefinition());
				}
			}
		}
		return tx;
	}
	
	
	/**
	 * 默认pre_commit和commit合并到commit一个方法中
	 * <p>	但实际执行流程还是一步一步来，只是两个方法合并成一个
	 */
	public void commit() {
		//	如果当前处于can_commit状态，执行预提交
		if (DistributedTransactionStatus.CAN_COMMIT.equals(this.status())) {
			super.preCommit();
		}
		//	执行提交
		super.commit();
	}
	
	
	/**
	 * can_commit阶段做的事情
	 * <p>	取数据库连接，开启事务对象
	 */
	@Override
	protected void doCanCommit() {
		try {
			this.tx = getDBTransaction();
		} catch (Exception e) {throw e;}
	}
	
	
	/**
	 * commit阶段做的事情
	 * <p>	真是提交事务
	 */
	@Override
	protected void doCommit() {
		dataSourceTransactionManager.commit(tx);
	}
	
	
	/**
	 * can_commit阶段发生了rollback
	 */
	@Override
	protected void doRollbackWithCanCommit() {
		dataSourceTransactionManager.rollback(tx);
	}
	/**
	 * pre_commit阶段发生了rollback
	 */
	@Override
	protected void doRollbackWithPreCommit() {
		dataSourceTransactionManager.rollback(tx);
	}
	/**
	 * commit阶段发生了rollback
	 */
	@Override
	protected void doRollbackWithCommited() {
		if (compensation != null) {
			compensation.compensation();
		}
	}


	/**
	 * 事物定义
	 */
	protected TransactionDefinition transactionDefinition() {
		//	设置本地事务的传播性：挂起原有事务，新开事务
		DefaultTransactionDefinition ed = new DefaultTransactionDefinition();
		ed.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
		return ed;
	}
	
	
	/**
	 * begin -> can_commot 直接跑过
	 */
	@Override
	protected boolean isWaitBeginToCanCommit() {
		return false;
	}
	/**
	 * pre_commit -> commit 需要等待状态统一
	 */
	@Override
	protected final boolean isWaitPreCommitToCommit() {
		return true;
	}
	/**
	 * commit -> finised 需要等待状态统一
	 */
	@Override
	protected boolean isWaitCommitToFinished() {
		return true;
	}


	public DataSourceTransactionManager getDataSourceTransactionManager() {
		return dataSourceTransactionManager;
	}
	public void setDataSourceTransactionManager(DataSourceTransactionManager dataSourceTransactionManager) {
		this.dataSourceTransactionManager = dataSourceTransactionManager;
	}
}
